package com.zodiac.app.szse;

import com.itextpdf.text.exceptions.InvalidPdfException;
import com.itextpdf.text.pdf.PdfReader;

import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class Utils {
    /**
     * 检查PDF是否有效
     *
     * @param pdfIn
     * @return
     */
    public static boolean checkPdfIsValid(byte[] pdfIn) {
        return checkPdfIsValid((Object) pdfIn);
    }

    /**
     * 检查PDF是否有效
     *
     * @param pdfIn
     * @return
     */
    public static boolean checkPdfIsValid(InputStream pdfIn) {
        return checkPdfIsValid((Object) pdfIn);
    }

    /**
     * 检查PDF是否有效
     *
     * @param pdfIn
     * @return
     */
    public static boolean checkPdfIsValid(File pdfIn) {
        return checkPdfIsValid((Object) pdfIn);
    }

    /**
     * 检查PDF是否有效
     *
     * @param pdf
     * @return
     */
    private static boolean checkPdfIsValid(Object pdf) {
        try {
            if (File.class.isAssignableFrom(pdf.getClass())) {
                new PdfReader(((File) pdf).getAbsolutePath());
                return true;
            }
            if (InputStream.class.isAssignableFrom(pdf.getClass())) {
                new PdfReader((InputStream) pdf);
                return true;
            }
            if (byte[].class.isAssignableFrom(pdf.getClass())) {
                new PdfReader((byte[]) pdf);
                return true;
            }
            throw new RuntimeException("不支持的PDF检查对象 -> " + pdf);
        } catch (Exception e) {
            // ignore
            if (!InvalidPdfException.class.isAssignableFrom(e.getClass())) {
                e.printStackTrace();
            }
            return false;
        }
    }

    /**
     * 抽取页眉与页脚行
     *
     * @param lines
     * @return
     */
    private static Map<Integer, String> extractHeaderWithFooterLine(List<String> lines) {
        final int size = lines.size();
        final AtomicInteger pageNo = new AtomicInteger(1);
        final Map<Integer, String> headerWithFooterMap = new TreeMap<>();

        for (int i = 0; i < size; i++) {
            final String content = lines.get(i).trim();
            // 报告页码，一般在页眉或页脚的位置
            if (content.matches("\\d+") && content.equals(String.valueOf(pageNo.get()))) {
                headerWithFooterMap.put(i, content);
                pageNo.incrementAndGet();
                continue;
            }
            // 报告标题，一般在页眉或页脚的位置
            if (content.replace(" ", "").matches(".*\\d{4}年.+报告(全文)?$")) {
                headerWithFooterMap.put(i, content);
                if (i > 1 && lines.get(i - 1).replace(" ", "").matches(".+股份有限公司$")) {
                    headerWithFooterMap.put(i - 1, lines.get(i - 1));
                }
                continue;
            }
        }
        return headerWithFooterMap;
    }

    /**
     * 移除页眉和页脚行
     *
     * @param lines
     */
    public static List<String> removeHeaderWithFooterLine(List<String> lines) {
        Map<Integer, String> headerWithFooterLineMap = extractHeaderWithFooterLine(lines);
        Set<Integer> toRemoveLineNos = headerWithFooterLineMap.keySet();
        return IntStream.range(0, lines.size()).boxed().filter(i -> !toRemoveLineNos.contains(i)).map(lines::get).collect(Collectors.toList());
    }

    /**
     * 从财务内容中抽取财务数据，进行结构化封装
     *
     * @param financialContent
     * @return
     */
    public static List<Financial> extractFinancialData(List<String> financialContent) {
        List<String> filtered = financialContent.stream().map(line -> line.replaceAll("^\\s+", "")).collect(Collectors.toList());
        final List<Financial> financialList = new ArrayList<>();
        int size = filtered.size();

        for (int i = 0; i < size; i++) {
            String line = filtered.get(i);
            // 空行
            if (line.trim().isEmpty()) {
                continue;
            }

            // 以3个空格结尾，看做完整的一行且没有数据
            if (line.matches(".+\\s{3,}$")) {
                financialList.add(new Financial(line.trim()));
                continue;
            }

            // 不以为空结尾的行
            if (!line.matches(".*\\s$")) {
                String name = line + filtered.get(i + 1).trim();
                String valueLine = filtered.get(i + 2);
                if (!valueLine.replaceAll("[-,.()\\s]+", "").matches("\\d+")) {
                    i++;
                    financialList.add(new Financial(name));
                    continue;
                }
                i += 2;
                String[] valueItems = valueLine.trim().split("\\s+");
                if (valueItems.length == 2) {
                    financialList.add(new Financial(name, valueItems[0], valueItems[1]));
                    continue;
                }
                if (valueLine.matches("^\\s+.+")) {
                    financialList.add(new Financial(name, null, valueItems[0]));
                    continue;
                }
                financialList.add(new Financial(name, valueItems[0], null));
                continue;
            }

            // 以空格结尾的行
            String[] items = line.trim().split("\\s+");
            if (items.length == 3) {
                financialList.add(new Financial(items[0], items[1], items[2]));
                continue;
            }
            if (items.length == 2) {
                if (line.trim().matches(".+\\s{2,}.+")) {
                    financialList.add(new Financial(items[0], null, items[1]));
                } else {
                    financialList.add(new Financial(items[0], items[1], null));
                }
                continue;
            }
            // 无法解析的报表行(目前知道的情况：断页造成的，将内容作为上一行名称的结尾)
            final Financial last = financialList.get(financialList.size() - 1);
            last.setName(last.getName() + line.trim());
        }
        final AtomicInteger no = new AtomicInteger(1);
        financialList.forEach(v -> v.setNo(no.getAndIncrement()));
        return financialList;
    }
}
